package com.boot.security.server.hitapp.controller;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.boot.security.server.dao.*;
import com.boot.security.server.dto.*;
import com.boot.security.server.model.*;
import com.boot.security.server.service.SmsService;
import com.boot.security.server.service.TokenService;
import com.boot.security.server.service.UserService;
import com.boot.security.server.utils.*;
import com.fasterxml.jackson.core.JsonParser;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.jfinal.kit.PathKit;
import com.jpay.ext.kit.*;
import com.jpay.util.StringUtils;
import com.jpay.weixin.api.WxPayApi;
import com.jpay.weixin.api.WxPayApiConfigKit;
import io.swagger.annotations.ApiOperation;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.*;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import sun.net.www.http.HttpClient;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.ws.Action;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;

@RestController
@RequestMapping("/api/wx")
public class WeixinController {

    private static Logger log = LoggerFactory.getLogger(WeixinController.class);

    @Autowired
    private UserService userService;

    @Autowired
    private WxMpService wxMpService;
    @Autowired
    private AppApponitDao appApponitDao;
    @Autowired
    private AppAccountDao appAccountDao;
    @Autowired
    private AppPaymentOrderDao appPaymentOrderDao;
    @Autowired
    private AppTradePaynoDao appTradePaynoDao;
    @Autowired
    private AppVisitPayDao appVisitPayDao;
    @Autowired
    private PermissionDao permissionDao;
    @Autowired
    private UserDao userDao;

    @Value("${wx.appId}")
    private String appId;

    @Value("${wx.mch_id}")
    private String mch_id;
    @Value("${wxgzh.certPath}")
    private String certPath;
    @Value("${wxgzh.appId}")
    private String wxappId;

    @Value("${wxgzh.appSecret}")
    private String wxappSecret;
    @Autowired
    private SmsService smsService;

    @Autowired
    private TokenService tokenService;

    // partnerKey
    //notify_url
    @Value("${wx.partnerKey}")
    private String partnerKey="nTqIHtZM7CKVcC9jgcRvMYhYZCy0aknz";
    @Value("${wx.notify_url}")
    private String notify_url;
    @Value("${wx.appSecret}")
    private String appSecret;

    @Value("${wx.grantType}")
    private String grantType;
    // wx.grantType=authorization_code
    @Autowired
    private RestTemplate restTemplate;
    @Value("${wx.requestUrl}")
    private String requestUrl;
    @Autowired
    private RedisTemplate redisTemplate;
    // wx.requestUrl=https://api.weixin.qq.com/sns/jscode2session

    @RequestMapping("/session")
    public R getSession(@RequestParam(required = true) String code) {
        return this.getSessionByCode(code);
    }

    @RequestMapping("/login")
    public R getloginwx(@RequestBody Map<String, String> loginpagrm) {
        LogBacks.info("微信授权直接登陆--------------");
        String username = loginpagrm.get("username").toString();
        String password = loginpagrm.get("password").toString();
        String openid = "";
        if (!StringUtils.isBlank(loginpagrm.get("openid").toString())) {
            openid = loginpagrm.get("openid").toString();
        }

        Map<String, String> map = new HashMap<String, String>();
        String redirectURLs = "";
        String flag = "0";
        //  AppAccount appAccount
        if (!StringUtils.isBlank(openid)) {
            LogBacks.info("微信授权直接登陆");

            SysUser sysUser = userDao.getByopenid(openid);
            if (sysUser == null) {
                return new R<>("", "请完成手机验证！", 99);
            }
            LoginUser loginUser = new LoginUser();
            BeanUtils.copyProperties(sysUser, loginUser);

            List<Permission> permissions = permissionDao.listByUserId(sysUser.getId());
            loginUser.setPermissions(permissions);


            Token token = tokenService.saveToken(loginUser);
            String tokens = token.getToken();
            redirectURLs = "http://zkwl.tpddns.cn:8086/api/wx/authorize?logintype=app";
            String nickname = sysUser.getNickname();
            String cardno = "";
            String idCard = "";
            String cardtype = "";
            String responsetype = "";
            String phone = sysUser.getPhone();

            AppAccount apps = appAccountDao.getByusers(openid, phone);
            if (apps != null) {
                flag = "1";
                cardno = apps.getCardno();
                idCard = apps.getIdCard();
                cardtype = apps.getCardtype();
                responsetype = apps.getResponsetype();
                phone = apps.getPhoneNo();
            }

            map.put("token", tokens);
            map.put("openid", openid);
            map.put("username", nickname);
            map.put("cardno", cardno);
            map.put("idCard", idCard);
            map.put("cardtype", cardtype);
            map.put("responsetype", responsetype);
            map.put("phone", phone);
            map.put("redirectURLs", redirectURLs);
            map.put("flag", flag);

        } else {
            SysUser u = userDao.getUser(username);
            if (u == null) {
                return new R<>("", "用户不存在或密码错误！", 99);
            }
            //  RestTemplate restTemplate = new RestTemplate();
            String urllog = "http://zkwl.tpddns.cn:8086/login";
//       String urllog = "http://zkwl.tpddns.cn:8086/login";
            MultiValueMap<String, String> maps = new LinkedMultiValueMap<String, String>();
            maps.add("username", username);
            maps.add("password", password);
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(maps, headers);
            String response = restTemplate.postForEntity(urllog, request, String.class).getBody();
            LogBacks.info("response:" + response);
            JSON jsonret = JSON.parseObject(response);
            String retcode = ((JSONObject) jsonret).getString("code");
            String msgs = ((JSONObject) jsonret).getString("message");
            if (!StringUtils.isBlank(retcode)) {
                return new R<>("", msgs, 99);
            }
            String openids = ((JSONObject) jsonret).getString("openid");
            AppAccount apps = appAccountDao.getByusers(openid, username);
            if (apps != null) {

                String token = ((JSONObject) jsonret).getString("token");
                String myPublicDomain = "http://zkwl.tpddns.cn:8086/pages/yihu/index.html";//内网映射域名，使用ngrok
                String url = "http://zkwl.tpddns.cn:8086/pages/yihu/index.html";//内网映射域名，使用ngrok
                String redirectURL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + wxappId
                        + "&redirect_uri=" + URLEncoder.encode(myPublicDomain)
                        + "&response_type=code"
                        + "&scope=snsapi_userinfo"
                        + "&state=STATE#wechat_redirect";
                String returnUrl = "";
                Map<String, String> resultMap = new HashMap<String, String>();
                //   redirectURLs = wxMpService.oauth2buildAuthorizationUrl(url, WxConsts.OAuth2Scope.SNSAPI_USERINFO, URLEncoder.encode(returnUrl));
                log.info("【微信网页授权】获取code,redirectURL={}", redirectURLs);

                //    redirectURLs = "http://zkwl.tpddns.cn:8086/api/wx/authorize?logintype=app";
                redirectURLs = "http://zkwl.tpddns.cn:8086/api/wx/authorize?logintype=app";
                log.info("【微信网页授权】获取code,redirectURL={}", redirectURLs);

                String nickname = "ccc";
                map.put("token", token);
                map.put("openid", openids);
                map.put("username", nickname);
                map.put("cardno", apps.getCardno());
                map.put("idCard", apps.getIdCard());
                map.put("cardtype", apps.getCardtype());
                map.put("responsetype", apps.getResponsetype());
                map.put("phone", apps.getPhoneNo());
                map.put("redirectURLs", redirectURLs);
                map.put("hostcode", "888888");

            }
        }
        return new R<>(map);
    }


    // public R addinfo(@RequestBody Map<String, String> regages){

    @PostMapping("/regno")
    public R addinfo(@RequestBody appaccountdto regages) {

        log.info("ykd-注册操作");
        log.info("ykd-注册操作+loginpagrm:");
        String codem = regages.getCodem();
        String PhoneNo = regages.getPhoneNo();
        log.info("ykd-注册操作+codem:" + codem);
        log.info("ykd-注册操作+PhoneNo:" + PhoneNo);
        Object codeObj = redisTemplate.opsForValue().get(regages.getPhoneNo());

        if (codeObj == null) {
            return new R<>("", "验证码失效，请重新获取！", 99);
        }
        String saveCode = codeObj.toString();
        log.info("ykd-注册操作+验证码:+" + saveCode);
        if (StringUtils.isBlank(saveCode)) {
            redisTemplate.delete(codem);
            return new R<>("", "验证码错误", 99);
        }
        //  log.info("ykd-注册操作+getPhone:"+regages.getPhone());
        SysUser u = userService.getUser(regages.getPhoneNo());
        if (u != null) {
            return new R<>("", "用户已经存在！", 99);
        }

        //   AppAccount   users=new AppAccount();
        UserDto userDto = new UserDto();
        //   users.setPhoneNo(regages.getPhoneNo());
        //    users.setOpenId(regages.getOpenId());
        userDto.setUsername(regages.getPhoneNo());
        userDto.setNickname(regages.getRealName());
        userDto.setPassword(regages.getPassword());
        userDto.setOpenid(regages.getOpenId());
        userDto.setFlag("1");
        userDto.setPhone(regages.getPhoneNo());
        userDto.setStatus(1);
        List<Long> list = new ArrayList<Long>();
        long[] a = new long[0];
        Long l = 1L;
        list.add(l);
        userDto.setRoleIds(list);
        //  appAccountDao.save(users);
        if (userDao.save(userDto) == 0) ;
        {
            return new R<>("", "保存成功");
        }
        //   return new R<>("","插入成功");
        //  return new R<>(appAccountDao.save(appAccount));
    }
//    @RequestMapping("/reg")
//    public R getloginwx(@RequestParam(required = true) String code) {
//        return this.getSessionByCode(code);
//    }


    @RequestMapping("/smscode")
    public R getloginsms(@RequestParam(required = true) String phone) {
        if (StringUtils.isBlank(phone)) {
            return new R("", "为空了");
        }
        smsService.sendSmsCode(phone);
        return new R();
    }

    private R getSessionByCode(String code) {
        String url = this.requestUrl + "?appid=" + appId + "&secret=" + appSecret + "&js_code=" + code + "&grant_type="
                + grantType;
        Map<String, String> map = new HashMap<String, String>();
        // 发送请求
//        String data = HttpUtil.get(url);
//        log.debug("请求地址：{}", url);
//        log.debug("请求结果：{}", data);
//        ObjectMapper mapper = new ObjectMapper();
//        Map<String, Object> json = null;
//        try {
//            json = mapper.readValue(data, Map.class);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
        //微信的接口
        String erroe = "微信接口异常";
        try {

            String urls = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId +
                    "&secret=" + appSecret + "&js_code=" + code + "&grant_type=authorization_code";

            //     RestTemplate restTemplate = new RestTemplate();
            //进行网络请求,访问url接口
            ResponseEntity<String> responseEntity = restTemplate.exchange(urls, HttpMethod.GET, null, String.class);
            //根据返回值进行后续操作
            if (responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) {
                String sessionData = responseEntity.getBody();
                JSONObject json = JSON.parseObject(sessionData);
                erroe = json.toString();
                //获取会话密钥（session_key）
                log.info(sessionData);
                String session_key = json.get("session_key").toString();
                //用户的唯一标识（openid）
                String openid = (String) json.get("openid");
                String username;
                String jifen;
                String vipdj;
                //判断是否存该用户，如果不存在注册用户，并且登录后获取token


                String urllog = "http://127.0.0.1:8080/login";
                MultiValueMap<String, String> maps = new LinkedMultiValueMap<String, String>();
                maps.add("username", "");
                maps.add("password", "888888");
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
                HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(maps, headers);
                String response = restTemplate.postForEntity(urllog, request, String.class).getBody();
                JSON jsonret = JSON.parseObject(response);
                String token = ((JSONObject) jsonret).getString("token");
//            Gson gson = new Gson();
//            //解析从微信服务器获得的openid和session_key;
//            WeChatSession weChatSession = gson.fromJson(sessionData, WeChatSession.class);
//            //获取用户的唯一标识
//            String openid = weChatSession.getOpenid();
//            //获取会话秘钥
//            String session_key = weChatSession.getSession_key();
//            //下面就可以写自己的业务代码了
//            //最后要返回一个自定义的登录态,用来做后续数据传输的验证

                map.put("username", "");
                map.put("session_key", session_key);
                map.put("openid", openid);
                map.put("jifen", "");
                map.put("vipdj", "");
            }

        } catch (Exception e) {
            log.error(Thread.currentThread().getStackTrace()[1].getMethodName() + "发生的异常是: ", e);
            map.put("msgs", e.toString());
            return new R<>(false, "返回错误了" + erroe);
        }
        // 形如{"session_key":"6w7Br3JsRQzBiGZwvlZAiA==","openid":"oQO565cXXXXXEvc4Q_YChUE8PqB60Y"}的字符串
        // return JSON.toJSONString(map);
        return new R<>(map);
    }

    /**
     * 小程序微信支付的第一步,统一下单
     *
     * @return
     * @author zgd
     * @time 2018年7月9日17:53:35
     */
    @RequestMapping("/createUnifiedOrder")
    @ResponseBody
    public AjaxJsonVo createUnifiedOrder(@RequestBody String dingdangl) {
        AjaxJsonVo aj = new AjaxJsonVo();
        aj.setSuccess(false);
        String orderId = "";//request.getParameter("orderId");
        //接受参数(openid)
        String openid = "";// request.getParameter("openid");
        if (StringUtils.isAnyBlank(orderId, openid)) {
            aj.setMsg("支付失败,支付所需参数缺失");
            return aj;
        }
        //这里调用service层根据订单id获取订单数据,这里省略不表
//        Map<String, String> mapBasic =(Map<String, String>)dingdanglDao.getBydd("22222222222");
//        if (mapBasic == null) {
//            aj.setMsg("支付失败,暂时无法获取到您的订单数据,请稍后再试");
//            return aj;
//        }
        String return_msg = "统一订单失败";
        try {

            //支付金额 **金额不能有小数点,单位是分!!**
            BigDecimal price = new BigDecimal("40");
            BigDecimal beishu = new BigDecimal("100");
            BigDecimal priceFee = price.multiply(beishu);
            //商家订单号
            String orderNo = ""; //mapBasic.get("orderNo").toString();

            //创建 时间戳
            String timeStamp = Long.valueOf(System.currentTimeMillis()).toString();
            //生成32位随机数
            UUID uuid = UUID.randomUUID();
            String nonceStr = uuid.toString().replaceAll("-", "");
            //商品描述
            String body = "XX商城-支付订单";
            //创建hashmap(用户获得签名)
            SortedMap<String, String> paraMap = new TreeMap<String, String>();
            //设置请求参数(小程序ID)
            paraMap.put("appid", appId);
            //设置请求参数(商户号)
            paraMap.put("mch_id", mch_id);
            //设置请求参数(随机字符串)
            paraMap.put("nonce_str", nonceStr);
            //设置请求参数(商品描述)
            paraMap.put("body", body);
            //设置请求参数(商户订单号)
            paraMap.put("out_trade_no", orderNo);
            //设置请求参数(总金额)
            paraMap.put("total_fee", priceFee.toBigInteger().toString());
            //设置请求参数(终端IP) 如果是springmvc,或者能获取到request的servlet,用下面这种
            paraMap.put("spbill_create_ip", "");
            //设置请求参数(通知地址)
            paraMap.put("notify_url", notify_url);
            //设置请求参数(交易类型)
            paraMap.put("trade_type", String.valueOf(WxPayApi.TradeType.JSAPI));
            //设置请求参数(openid)(在接口文档中 该参数 是否必填项 但是一定要注意 如果交易类型设置成'JSAPI'则必须传入openid)
            paraMap.put("openid", openid);
            //MD5运算生成签名，这里是第一次签名，用于调用统一下单接口
            String sign = PaymentKit.createSign(paraMap, partnerKey);
            paraMap.put("sign", sign);
            //统一下单,向微信api发送数据
            log.info("微信小程序统一下单发送的数据: " + paraMap.toString());
            String xmlResult = WxPayApi.pushOrder(false, paraMap);
            log.info("微信小程序统一下单接受返回的结果: " + xmlResult);
            //转成xml
            Map<String, String> map = PaymentKit.xmlToMap(xmlResult);
            //返回状态码
            String return_code = (String) map.get("return_code");
            return_msg = return_msg + ", " + (String) map.get("return_msg");
            //返回给小程序端需要的参数
            Map<String, String> returnMap = new HashMap<String, String>();
            if (WXPayConstants.SUCCESS.equals(return_code)) {
                //返回的预付单信息
                returnMap.put("appId", appId);
                returnMap.put("nonceStr", nonceStr);
                String prepay_id = (String) map.get("prepay_id");
                returnMap.put("package", "prepay_id=" + prepay_id);
                returnMap.put("signType", "MD5");
                //这边要将返回的时间戳转化成字符串，不然小程序端调用wx.requestPayment方法会报签名错误
                returnMap.put("timeStamp", timeStamp);
                //拼接签名需要的参数
                //再次签名，这个签名用于小程序端调用wx.requesetPayment方法
                String paySign = PaymentKit.createSign(returnMap, partnerKey).toUpperCase();
                returnMap.put("paySign", paySign);
                aj.setObj(returnMap);
                aj.setMsg("操作成功");
                aj.setSuccess(true);
                return aj;
            } else {
                aj.setMsg(getMsgByCode(return_code));
                log.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ">>>" + return_msg);
            }
        } catch (Exception e) {
            log.error(Thread.currentThread().getStackTrace()[1].getMethodName() + "发生的异常是: ", e);
            aj.setMsg("微信支付下单失败,请稍后再试");
        }
        return aj;
    }

    /**
     * 判断返回的return_code,给前端相应的提示
     *
     * @param return_code
     * @return
     * @author zgd
     * @time 2018年7月9日17:53:13
     */
    private String getMsgByCode(String return_code) {
        switch (return_code) {
            case "NOTENOUGH":
                return "您的账户余额不足";
            case "ORDERPAID":
                return "该订单已支付完成,请勿重复支付";
            case "ORDERCLOSED":
                return "当前订单已关闭，请重新下单";
            case "SYSTEMERROR":
                return "系统超时，请重新支付";
            case "OUT_TRADE_NO_USED":
                return "请勿重复提交该订单";
            default:
                return "网络正在开小差,请稍后再试";
        }
    }

    @ApiOperation(value = "手机订单支付完成后回调")
    @RequestMapping(value = "/wxPay/notify", method = {RequestMethod.GET, RequestMethod.POST})
    @Transactional
    public String WXPayBack(HttpServletRequest request, HttpServletResponse response) {


        //获取所有的参数
        LogBacks.info("回调接口");
        StringBuffer sbf = new StringBuffer();

        // 支付结果通用通知文档: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
        String xmlMsg = HttpKit.readData(request);
        log.info("支付通知=" + xmlMsg);
        Map<String, String> params = PaymentKit.xmlToMap(xmlMsg);
        String result_code = params.get("result_code");
        //参数
        String attach = params.get("attach");
//        String appid  = params.get("appid");
//        //商户号
//        String mch_id  = params.get("mch_id");
//        String openId      = params.get("openid");
//        //交易类型
//        String trade_type      = params.get("trade_type");
//        //付款银行
//        String bank_type      = params.get("bank_type");
//        // 总金额
//        String total_fee     = params.get("total_fee");
//        //现金支付金额
//        String cash_fee     = params.get("cash_fee");
//        // 微信支付订单号
        String transaction_id      = params.get("transaction_id");
//        // 商户订单号
        String out_trade_no      = params.get("out_trade_no");
        // 支付完成时间，格式为yyyyMMddHHmmss
        String time_end      = params.get("time_end");
        /////////////////////////////以下是附加参数///////////////////////////////////

//        String fee_type      = params.get("fee_type");
//        String is_subscribe      = params.get("is_subscribe");
//        String err_code      = params.get("err_code");
//        String err_code_des      = params.get("err_code_des");
        // 注意重复通知的情况，同一订单号可能收到多次通知，请注意一定先判断订单状态
        // 避免已经成功、关闭、退款的订单被再次更新
        AppTradePayno appTradePayno=appTradePaynoDao.getByOuttradeno(out_trade_no);
        String status=appTradePayno.getFeestatus();
        if(status.equals(AppConstants.FEE_STATUS_DEFAULT)){
            //校验返回来的支付结果,根据已经配置的密钥
            if (PaymentKit.verifyNotify(params, partnerKey)) {
                if ((WXPayConstants.SUCCESS).equals(result_code)) {
                    // 校验通过. 更改订单状态为已支付, 修改库存
                    //更新订单信息
                    log.warn("更新订单信息:" + attach);
                    appTradePayno.setNotifyid(transaction_id);
                    appTradePayno.setNotifytime(time_end);
                    appTradePayno.setFeestatus(AppConstants.FEE_STATUS_YZF);
                    appTradePayno.setOrderstatus(AppConstants.ORDER_STATUS_SUCCESS);
                    appTradePaynoDao.update(appTradePayno);
                    AppPaymentOrder order=new AppPaymentOrder();
                    order.setTradeno(appTradePayno.getTradeno());
                    order=appPaymentOrderDao.getBylist(order);
                    order.setPaystaus(AppConstants.ORDER_STATUS_SUCCESS);
                    appPaymentOrderDao.update(order);
                    //修改缴费记录缴费状态
                    AppVisitPay appVisitPay=new AppVisitPay();
                    appVisitPay.setTradeno(appTradePayno.getTradeno());
                    appVisitPay=appVisitPayDao.findInfo(appVisitPay);
                    appVisitPay.setPaystaus(AppConstants.ORDER_STATUS_SUCCESS);
                    appVisitPayDao.update(appVisitPay);
                    //发送通知等
                    Map<String, String> xml = new HashMap<String, String>();
                    xml.put("return_code", "SUCCESS");
                    xml.put("return_msg", "OK");
                    return PaymentKit.toXml(xml);
                }
            }
        }
        return null;

    }

    //微信退费
    public static String readData(HttpServletRequest request) {
        BufferedReader br = null;
        try {
            StringBuilder ret;
            br = request.getReader();

            String line = br.readLine();
            if (line != null) {
                ret = new StringBuilder();
                ret.append(line);
            } else {
                return "";
            }

            while ((line = br.readLine()) != null) {
                ret.append('\n').append(line);
            }

            return ret.toString();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
    }

    @RequestMapping("/weixinInfo")
    //   @ResponseBody
    public R weixinInfo(@RequestParam(required = true) HttpServletRequest request) {


        String code = request.getParameter("code");
        System.out.println(code);
        if (code != null) {
            //获取openid和access_token的连接
            String getOpenIdUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=APPSECRET&code=CODE&grant_type=authorization_code";
            //获取返回的code
            String requestUrl = getOpenIdUrl.replace("CODE", code);
            //       RestTemplate restTemplate = new RestTemplate();
            //进行网络请求,访问url接口
            //   ResponseEntity<String> responseEntity =
            //根据返回值进行后续操作

//                HttpClient httpClient = new DefaultHttpClient();
//                HttpGet httpGet = new HttpGet(requestUrl);
//                ResponseHandler<String> responseHandler = new BasicResponseHandler();
            //向微信发送请求并获取response
            ResponseEntity<String> responseEntity = restTemplate.exchange(requestUrl, HttpMethod.GET, null, String.class);
            if (responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) {
                String sessionData = responseEntity.getBody();
                JSONObject json = JSON.parseObject(sessionData);
                //获取会话密钥（session_key）
                log.info(sessionData);
                String access_token = json.get("access_token").toString();
                //用户的唯一标识（openid）
                String openid = (String) json.get("openid");
                System.out.println("=======================用户access_token==============");
                System.out.println(access_token);
                System.out.println(openid);
            }
//                System.out.println("=========================获取token===================");
//                System.out.println(responseEntity);
//                JsonParser parser = new JsonParser();
//                JsonObject jsonObject = (JsonObject) parser.parse(responseEntity);
//                String access_token = jsonObject.get("access_token").getAsString();
//                String openId = jsonObject.get("openid").getAsString();
//                System.out.println("=======================用户access_token==============");
//                System.out.println(access_token);
//                System.out.println(openId);
//                //获取用户基本信息的连接
//                String getUserInfo = "https://api.weixin.qq.com/sns/userinfo?  access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
//                String userInfoUrl = getUserInfo.replace("ACCESS_TOKEN", access_token).replace("OPENID", openId);
//                HttpGet httpGetUserInfo = new HttpGet(userInfoUrl);
//                String userInfo = httpClient.execute(httpGetUserInfo,responseHandler);
//                //微信那边采用的编码方式为ISO8859-1所以需要转化
//                String json = new String(userInfo.getBytes("ISO-8859-1"),"UTF-8");
//                System.out.println("====================userInfo==============================");
//                JsonObject jsonObject1 = (JsonObject) parser.parse(json);
//                String nickname = jsonObject1.get("nickname").getAsString();
//                String city = jsonObject1.get("city").getAsString();
//                String province = jsonObject1.get("province").getAsString();
//                String country = jsonObject1.get("country").getAsString();
//                String headimgurl = jsonObject1.get("headimgurl").getAsString();
//                //性别  1 男  2 女  0 未知
//                Integer sex = jsonObject1.get("sex").getAsInt();
//                System.out.println("昵称"+nickname);
//                System.out.println("城市"+city);
//                System.out.println("省"+province);
//                System.out.println("国家"+country);
//                System.out.println("头像"+headimgurl);
//                System.out.println("性别"+sex);
//                System.out.println(userInfo);
        }
        return new R();
    }


    /**
     * 小程序微信支付的第一步,统一下单
     *
     * @return
     * @author zgd
     * @time 2018年7月9日17:53:35
     */
    @RequestMapping("/dingwei")
    @ResponseBody
    public R getdizhi(@RequestBody Map<String, String> params) {
        String lng = params.get("lng");
        //接受参数(openid)
        String lat = params.get("lat");

        LocationUtils.getLocation(lng, lat);

        return new R<>(LocationUtils.getLocation(lng, lat));
    }

    @GetMapping("/authorize")
    public R authorize(@RequestParam("logintype") String logintype, HttpServletResponse response) throws IOException {
        log.info("登陆类型--------------" + logintype);
        if (StringUtils.isBlank(logintype)) {
            return new R("", "访问类型错误！", 99);
        } else {
            if (logintype.equals("wx")) {
                //                String myPublicDomain = "http://wx.95weixin.com/api/wx/userInfo";//内网映射域名，使用ngrok
//        String url = "http://wx.95weixin.com/api/wx/weixinInfo";//内网映射域名，使用ngrok
                String myPublicDomain = "http://zkwl.tpddns.cn:8086/api/wx/userInfo";//内网映射域名，使用ngrok
                String url = "http://zkwl.tpddns.cn:8086/api/wx/weixinInfo";//内网映射域名，使用ngrok
                String redirectURL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + wxappId
                        + "&redirect_uri=" + URLEncoder.encode(myPublicDomain)
                        + "&response_type=code"
                        + "&scope=snsapi_userinfo"
                        + "&state=STATE#wechat_redirect";
                String returnUrl = "";
                Map<String, String> resultMap = new HashMap<String, String>();
                String redirectURLs = wxMpService.oauth2buildAuthorizationUrl(url, WxConsts.OAuth2Scope.SNSAPI_USERINFO, URLEncoder.encode(returnUrl));
                log.info("【微信网页授权】获取code,redirectURL={}", redirectURLs);
                response.sendRedirect(redirectURL);
                //  resultMap.put("openid","oO1_5wJ6kuhprcvTq0_p42aGGOFg");
                //   resultMap.put("redirectURLs",redirectURLs);
                return new R(resultMap);
            } else {
                String redirectURL = "http://zkwl.tpddns.cn:8086/pages/yihu/index.html?logintype=app";
                //response.sendRedirect(redirectURL);
                //     "redirect:" + returnUrl + "?openid=" + openId;
                response.sendRedirect(redirectURL);
            }
        }

////        String myPublicDomain = "http://wx.95weixin.com/api/wx/userInfo";//内网映射域名，使用ngrok
////        String url = "http://wx.95weixin.com/api/wx/weixinInfo";//内网映射域名，使用ngrok
//        String myPublicDomain = "http://zkwl.tpddns.cn:8086/api/wx/userInfo";//内网映射域名，使用ngrok
//        String url = "http://zkwl.tpddns.cn:8086/api/wx/weixinInfo";//内网映射域名，使用ngrok
//        String redirectURL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" +wxappId
//                + "&redirect_uri=" + URLEncoder.encode(myPublicDomain)
//                + "&response_type=code"
//                + "&scope=snsapi_userinfo"
//                + "&state=STATE#wechat_redirect";
//        String returnUrl="";
//        Map<String, String> resultMap =new  HashMap<String, String>();
//         String  redirectURLs= wxMpService.oauth2buildAuthorizationUrl(url, WxConsts.OAuth2Scope.SNSAPI_USERINFO, URLEncoder.encode(returnUrl));
//        log.info("【微信网页授权】获取code,redirectURL={}", redirectURLs);
//        response.sendRedirect(redirectURL);
//      //  resultMap.put("openid","oO1_5wJ6kuhprcvTq0_p42aGGOFg");
//     //   resultMap.put("redirectURLs",redirectURLs);
        return new R();
    }

    @GetMapping("/userInfo")
    public R userInfo(@RequestParam("code") String code,
                      @RequestParam("state") String returnUrl, HttpServletResponse response) throws Exception {

        log.info("【微信网页授权】code={}", code);
        log.info("【微信网页授权】state={}", returnUrl);
        WxMpOAuth2AccessToken wxMpOAuth2AccessToken;
        try {
            wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code);
        } catch (WxErrorException e) {
            log.info("【微信网页授权】{}", e);
            throw new Exception(e.getError().getErrorMsg());
        }
        String access_token = wxMpOAuth2AccessToken.getAccessToken();
        String openId = wxMpOAuth2AccessToken.getOpenId();
        log.info("【微信网页授权】openId={}", openId);
        Map<String, String> resultMap = new HashMap<String, String>();
        resultMap.put("openid", openId);
        resultMap.put("access_token", access_token);
        String lang = "zh_CN";
        WxMpUser wxMpUser = null;
        wxMpUser = this.wxMpService.getUserService().userInfo(openId, lang);

        String redirectURL = "http://zkwl.tpddns.cn:8086/pages/yihu/index.html?openid=" + openId;
        // resultMap.put("redirectURL",redirectURL);
        response.sendRedirect(redirectURL);
        //     "redirect:" + returnUrl + "?openid=" + openId;
        //   response.sendRedirect(redirectURL);
        return new R(resultMap);

    }


    /*
     * 微信公众平台授权登录
     */
    @RequestMapping(value = "/wxLogin", method = RequestMethod.GET)
    public String wxLogin(HttpServletRequest request, HttpServletResponse response) {
        String myPublicDomain = "http://zkwl.tpddns.cn:8086";//内网映射域名，使用ngrok
        //    String myPublicDomain = "http://zkwl.tpddns.cn:8086";//内网映射域名，使用ngrok
//		String backUrl = myPublicDomain + "/wxCallBack";

        /*  在确保微信公众账号拥有授权作用域（scope参数）的权限的前提下（服务号获得高级接口后，默认拥有scope参数中的snsapi_base和snsapi_userinfo）
         * ，引导关注者打开如下页面：
         * https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
         *
         * 尤其注意：
         * 由于授权操作安全等级较高，所以在发起授权请求时，微信会对授权链接做正则强匹配校验，
         * 如果链接的参数顺序不对，授权页面将无法正常访问
         * 跳转回调redirect_uri，应当使用https链接来确保授权code的安全性
         *
         */
        System.out.println("wxLogin------------");
        String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + wxappId
                + "&redirect_uri=" + URLEncoder.encode(myPublicDomain)
                + "&response_type=code"
                + "&scope=snsapi_userinfo"
                + "&state=STATE#wechat_redirect";
		/*try {
			response.sendRedirect(url);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}*/
        RestTemplate restTemplate = new RestTemplate();
        //进行网络请求,访问url接口
        //   ResponseEntity<String> responseEntity =
        //根据返回值进行后续操作

//                HttpClient httpClient = new DefaultHttpClient();
//                HttpGet httpGet = new HttpGet(requestUrl);
//                ResponseHandler<String> responseHandler = new BasicResponseHandler();
        //向微信发送请求并获取response
        ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, null, String.class);
        if (responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) {
            String sessionData = responseEntity.getBody();
            JSONObject json = JSON.parseObject(sessionData);

            //  JSONObject json = JSONObject.parseObject(url);//WxAuthUtil.doGetJson(url);
	/*	try {
			 json = WxAuthUtil.doGetJson(url);
		} catch (ClientProtocolException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}*/

            //获取code值
            String code = json.getString("code");
            System.out.println("json.code----------" + code);
            /* 获取code后，请求以下链接获取access_token：
             * 这里通过code换取的是一个特殊的网页授权access_token,与基础支持中的access_token（该access_token用于调用其他接口）不同
             */
            String url_1 = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + wxappId
                    + "&secret=" + wxappSecret
                    + "&code=" + code
                    + "&grant_type=authorization_code";
            JSONObject jsonObject = JSONObject.parseObject(url_1);
	/*	try {
			jsonObject = WxAuthUtil.doGetJson(url_1);
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}*/
            String openid = jsonObject.getString("openid");
            String tokentest = jsonObject.getString("access_token");

            /*
             * 拉去用户的信息
             */
            String infoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" + tokentest
                    + "&openid=" + openid
                    + "&lang=zh_CN";
            // JSONObject userInfo = WxAuthUtil.doGetJson(infoUrl);
		/*try {
			userInfo = WxAuthUtil.doGetJson(infoUrl);
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}*/
        }
        //1、使用微信用户信息直接登录，无需注册和绑定
        // request.setAttribute("info", userInfo);
        //request.getRequestDispatcher("/index.jsp").forward(request, response);
        return "testIndex";
    }


    /**
     * 扫码支付模式二
     * 已测试
     */
    @PostMapping("/scanCode")
    public R scanCode(@RequestBody Map<String, String> scanCodearg, HttpServletRequest request) {

//		String openId="o5NJx1dVRilQI6uUVSaBDuLnM3iM";
        String openId = scanCodearg.get("openId");
        String total_fee = scanCodearg.get("total_fee");

//        if (StrKit.isBlank(openId)) {
//            ajax.addError("openId is null");
//            renderJson(ajax);
//            return;
//        }
        if (StrKit.isBlank(total_fee)) {
            return new R("", "金额不能为空", 99);
        }

        String ip = IpKit.getRealIp(request);
        if (StrKit.isBlank(ip)) {
            ip = "127.0.0.1";
        }

        Map<String, String> params = WxPayApiConfigKit.getWxPayApiConfig()
                .setAttach("IJPay 测试  -By Javen")
                .setBody("IJPay 扫码支付2测试  -By Javen")
                .setOpenId(openId)
                .setSpbillCreateIp(ip)
                .setTotalFee(total_fee)
                .setTradeType(WxPayApi.TradeType.NATIVE)
                .setNotifyUrl(notify_url)
                .setOutTradeNo(String.valueOf(System.currentTimeMillis()))
                .build();

        String xmlResult = WxPayApi.pushOrder(false, params);

        log.info(xmlResult);
        Map<String, String> result = PaymentKit.xmlToMap(xmlResult);

        String return_code = result.get("return_code");
        String return_msg = result.get("return_msg");
        if (!PaymentKit.codeIsOK(return_code)) {
            System.out.println(return_msg);
            return new R(xmlResult, "异常", 99);
        }
        String result_code = result.get("result_code");
        if (!PaymentKit.codeIsOK(result_code)) {
            System.out.println(return_msg);
            return new R(xmlResult, "异常", 99);
        }
        //生成预付订单success

        String qrCodeUrl = result.get("code_url");
        String name = "payQRCode2.png";

        Boolean encode = ZxingKit.encode(qrCodeUrl, BarcodeFormat.QR_CODE, 3, ErrorCorrectionLevel.H, "png", 200, 200, PathKit.getWebRootPath() + File.separator + name);
        //          (qrCodeUrl, BarcodeFormat.QR_CODE, 3, ErrorCorrectionLevel.H, "png", 200, 200, PathKit.getWebRootPath()+ File.separator+name);
        if (encode) {
//			renderQrCode(qrCodeUrl, 200, 200);
            //在页面上显示
            return new R(name);
        }
        return new R();
    }

    /**
     * 刷卡支付
     * 已测试
     */
    @PostMapping("/micropay")
    public R micropay(@RequestBody Map<String, String> micropay, HttpServletRequest request) {
        String auth_code = micropay.get("auth_code");
        String total_fee = micropay.get("total_fee");

        if (StrKit.isBlank(total_fee)) {
            //    ajax.addError("支付金额不能为空");
            //   renderJson(ajax);
            //     return;
            return new R("", "支付金额不能为空", 99);
        }
        if (StrKit.isBlank(auth_code)) {
            //    ajax.addError("auth_code参数错误");
            //    renderJson(ajax);
            //return;
            return new R("", "auth_code参数错误", 99);
        }

        String ip = IpKit.getRealIp(request);
        if (StrKit.isBlank(ip)) {
            ip = "127.0.0.1";
        }

        Map<String, String> params = WxPayApiConfigKit.getWxPayApiConfig()
                .setAttach("IJPay 测试  -By Javen")
                .setBody("IJPay 刷卡支付测试 -By Javen")
                .setSpbillCreateIp(ip)
                .setTotalFee(total_fee)
                .setAuthCode(auth_code)
                .setTradeType(WxPayApi.TradeType.MICROPAY)
                .setNotifyUrl(notify_url)
                .setOutTradeNo(String.valueOf(System.currentTimeMillis()))
                .build();

        String xmlResult = WxPayApi.micropay(false, params);

        //同步返回结果
        log.info("xmlResult:" + xmlResult);

        Map<String, String> result = PaymentKit.xmlToMap(xmlResult);
        String return_code = result.get("return_code");
        String return_msg = result.get("return_msg");
        if (!PaymentKit.codeIsOK(return_code)) {
            //通讯失败
            String err_code = result.get("err_code");
            if (StrKit.notBlank(err_code)) {
                //用户支付中，需要输入密码
                if (err_code.equals("USERPAYING")) {
                    //等待5秒后调用【查询订单API】https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_2

                }
            }
            log.info("提交刷卡支付失败>>" + xmlResult);
            return new R("", "提交刷卡支付失败", 99);
        }

        String result_code = result.get("result_code");
        if (!PaymentKit.codeIsOK(result_code)) {
            //支付失败
            //支付失败
            log.info("支付失败>>" + xmlResult);
            String err_code_des = result.get("err_code_des");


            return new R(xmlResult, "支付失败", 99);
        }
        //支付成功
        return new R();
        //    re(xmlResult);
    }

    /**
     * 微信退款
     */
    @PostMapping("/refund")
    public R refund(@RequestBody Map<String, String> refund, HttpServletRequest request) {
        String transaction_id = refund.get("transactionId");
        String out_trade_no = refund.get("out_trade_no");

        if (com.jfinal.kit.StrKit.isBlank(out_trade_no) && com.jfinal.kit.StrKit.isBlank(transaction_id)) {
            //   renderText("transactionId、out_trade_no二选一");
            return new R("", "transactionId、out_trade_no二选一", 99);
        }

        Map<String, String> params = new HashMap<String, String>();
        params.put("appid", appId);
        params.put("mch_id", mch_id);
        params.put("nonce_str", System.currentTimeMillis() + "");
        if (com.jfinal.kit.StrKit.notBlank(transaction_id)) {
            params.put("transaction_id", transaction_id);
        } else {
            params.put("out_trade_no", out_trade_no);
        }
        params.put("out_refund_no", System.currentTimeMillis() + "");
        params.put("total_fee", "1");
        params.put("refund_fee", "1");
        params.put("sign", PaymentKit.createSign(params, partnerKey));
        String refunds = WxPayApi.orderRefund(false, params, certPath, mch_id);
        return new R(refunds);
    }

    /**
     * 微信退款查询
     */
    public void refundQuery() {
        String transaction_id = "";// getPara("transactionId");
        String out_trade_no = "";//getPara("out_trade_no");
        String out_refund_no = "";//getPara("out_refund_no");
        String refund_id = "";// getPara("refund_id");

        Map<String, String> params = new HashMap<String, String>();
        params.put("appid", appId);
        params.put("mch_id", mch_id);
        params.put("nonce_str", System.currentTimeMillis() + "");
        params.put("transaction_id", transaction_id);
        params.put("out_trade_no", out_trade_no);
        params.put("out_refund_no", out_refund_no);
        params.put("refund_id", refund_id);
        params.put("out_refund_no", System.currentTimeMillis() + "");
        params.put("sign", PaymentKit.createSign(params, partnerKey));
        String refund = WxPayApi.orderRefundQuery(false, params);
    }
    //orderquery

    /**
     * 微信订单状态查询
     */
    @PostMapping("/orderquery")
    public R orderquery(@RequestBody Map<String, String> orderquery, HttpServletRequest request) {
        String transaction_id = orderquery.get("transactionId");
        String out_trade_no = orderquery.get("out_trade_no");

        if (com.jfinal.kit.StrKit.isBlank(out_trade_no) && com.jfinal.kit.StrKit.isBlank(transaction_id)) {
            //   renderText("transactionId、out_trade_no二选一");
            return new R("", "transactionId、out_trade_no二选一", 99);
        }

        Map<String, String> params = new HashMap<String, String>();
        params.put("appid", appId);
        params.put("mch_id", mch_id);
        params.put("nonce_str", System.currentTimeMillis() + "");
        if (com.jfinal.kit.StrKit.notBlank(transaction_id)) {
            params.put("transaction_id", transaction_id);
        } else {
            params.put("out_trade_no", out_trade_no);
        }
        params.put("out_refund_no", System.currentTimeMillis() + "");
        params.put("total_fee", "1");
        params.put("refund_fee", "1");
        params.put("sign", PaymentKit.createSign(params, partnerKey));
        String refunds = WxPayApi.orderRefund(false, params, certPath, mch_id);
        return new R(refunds);
    }

}